package android.slc.utils;


import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import io.reactivex.rxjava3.annotations.NonNull;
import org.apache.commons.lang3.StringUtils;

import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.UUID;
import java.util.function.Function;

/**
 * 字符串操作类
 */
public class SlcStringUtils {
    /**
     * 如果一个string为空，则返回“--”
     *
     * @param text
     * @return
     */
    public static String toStringOfSimple(String text) {
        return toStringOfPlaceholder(text, "--");
    }

    /**
     * 如果一个string为空，则返回展位符
     *
     * @param text
     * @return
     */
    public static String toStringOfPlaceholder(String text, String placeholder) {
        if (StringUtils.isEmpty(text)) {
            return placeholder;
        }
        return text;
    }

    /**
     * 如果一个string为空，则返回展位符
     *
     * @param text
     * @return
     */
    public static String toStringOfReplace(String text, String replaceS, String replaceR) {
        if (StringUtils.isEmpty(text) || text.equals(replaceS)) {
            return replaceR;
        }
        return text;
    }

    /**
     * 获取UUID
     *
     * @return
     */
    public static String getSimpleUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }
    private static final String[] VAR_CUT_STR_TEMP = {"get", "set", "is"};

    /**
     * 将驼峰式命名的字符串转换为下划线方式并按照模板剪切多余字符。如果转换前的驼峰式命名的字符串为空，则返回空字符串
     *
     * @param var
     * @return
     */
    public static String var2UnderlineCase(String var) {
        return var2UnderlineCase(var, null);
    }

    /**
     * 将驼峰式命名的字符串转换为下划线方式并按照模板剪切多余字符。如果转换前的驼峰式命名的字符串为空，则返回空字符串
     *
     * @param var
     * @param excludeTemp
     * @return
     */
    public static String var2UnderlineCase(String var, String excludeTemp) {
        return var2UnderlineCase(var, excludeTemp, VAR_CUT_STR_TEMP);
    }

    /**
     * 将驼峰式命名的字符串转换为下划线方式并按照模板剪切多余字符。如果转换前的驼峰式命名的字符串为空，则返回空字符串
     *
     * @param var            变量名
     * @param excludeCutTemp 排除掉的字符串模板
     * @param varCutStrTemp  需要剪掉的字段模板
     * @return
     */
    public static String var2UnderlineCase(String var, String excludeCutTemp, @NonNull String[] varCutStrTemp) {
        if (StrUtil.isBlank(var)) {
            return var;
        }
        for (String varStr : varCutStrTemp) {
            if (var.startsWith(varStr) && !Objects.equals(varStr, excludeCutTemp)) {
                var = StrUtil.removePrefix(var, varStr);
                break;
            }
        }
        return StrUtil.toUnderlineCase(var);
    }

    /**
     * 将字符串转换为变量名
     *
     * @param var
     * @return
     */
    public static String methodName2FieldName(String var) {
        return methodName2FieldName(var, null);
    }

    /**
     * 将字符串转换为变量名
     *
     * @param var
     * @param excludeTemp
     * @return
     */
    public static String methodName2FieldName(String var, String excludeTemp) {
        return methodName2FieldName(var, excludeTemp, VAR_CUT_STR_TEMP);
    }

    /**
     * 将字符串转换为变量名
     *
     * @param var            变量名
     * @param excludeCutTemp 排除掉的字符串模板
     * @param varCutStrTemp  需要剪掉的字段模板
     * @return
     */
    public static String methodName2FieldName(String var, String excludeCutTemp, @NonNull String[] varCutStrTemp) {
        if (StrUtil.isBlank(var)) {
            return var;
        }
        for (String varStr : varCutStrTemp) {
            if (var.startsWith(varStr) && !Objects.equals(varStr, excludeCutTemp)) {
                var = var.substring(varStr.length());
                break;
            }
        }
        return StrUtil.lowerFirst(var);
    }

    /**
     * 获取变量名
     *
     * @param fieldGetter
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R> String getFieldName(FieldGetter<T, R> fieldGetter) {
        return getFieldName(fieldGetter, null);
    }

    /**
     * 将字符串转换为变量名
     *
     * @param excludeTemp
     * @param excludeTemp
     * @return
     */
    public static <T, R> String getFieldName(FieldGetter<T, R> fieldGetter, String excludeTemp) {
        return getFieldName(fieldGetter, excludeTemp, VAR_CUT_STR_TEMP);
    }

    public static <T, R> String getFieldName(FieldGetter<T, R> fieldGetter, String excludeCutTemp, @NonNull String[] varCutStrTemp) {
        try {
            String fieldName = fieldGetter.getFieldName(excludeCutTemp, varCutStrTemp);
            return fieldName;
        } catch (InvocationTargetException | IllegalAccessException e) {
            return "";
        }
    }

    public interface FieldGetter<T, R> extends Function<T, R>, Serializable {

        default String getFieldName(String excludeCutTemp, @NonNull String[] varCutStrTemp) throws InvocationTargetException, IllegalAccessException {
            Method method = ReflectUtil.getMethodByName(this.getClass(), "writeReplace");
            method.setAccessible(true);
            SerializedLambda serializedLambda = (SerializedLambda) method.invoke(this);
            String methodName = serializedLambda.getImplMethodName();
            for (String varStr : varCutStrTemp) {
                if (methodName.startsWith(varStr) && !Objects.equals(varStr, excludeCutTemp)) {
                    methodName = methodName.substring(varStr.length());
                    break;
                }
            }
            // 首字母变小写
            return methodName2FieldName(methodName, excludeCutTemp, varCutStrTemp);
        }

    }
}
